'use strict';

AModule.provider('A.Route', Route);

Route.$inject = [
    '$stateProvider',
    '$urlRouterProvider'
];
function Route($stateProvider, $urlRouterProvider) {

    var _filePrefix = '',
        _viewPrefix = '',
        _jsPathPrefix = '',// 加载 controller/service 的 js 文件的前缀
        _parent = '$$parent',
        _fullname = '$$fullname',
        _parseData;
    return {
        // provider access level
        filePrefix: filePrefix,
        viewPrefix: viewPrefix,
        jsPathPrefix: jsPathPrefix,
        setRoute: setRoute,
        // controller access level
        $get: function () {
            return {
                filePrefix: filePrefix,
                viewPrefix: viewPrefix,
                jsPathPrefix: jsPathPrefix,
                setRoute: setRoute
            };
        }
    };

    function filePrefix(prefix) {
        prefix && (_filePrefix = prefix);
        return _filePrefix;
    }

    function viewPrefix(prefix) {
        prefix && (_viewPrefix = prefix);
        return _viewPrefix;
    }

    function jsPathPrefix() {
        var args = arguments;
        if (!args.length) { // 没传参数 getter
            return _jsPathPrefix;
        }
        return (_jsPathPrefix = args[0] || '');
    }

    function setRoute(route) {
        _parseData = _parse(route);
        _init();
    }


    // private method
    // =====================================
    // 解析配置的 routeData
    function _parse(data, parents) {
        var result = {};
        parents = parents || [];
        angular.forEach(data, function (item) {
            // item 的上级 name
            item[_parent] = parents.join('.');
            parents.push(item.name);
            // 全称 用作 state.name. 上级的 parent + item.name
            var modelName = parents.join('.');
            item[_fullname] = modelName;
            result[modelName] = item;
            item.items && angular.extend(result, _parse(item.items, parents));
            // 保证同一级的下一次循环的 parents 一样, 在 parents.push(item.name) 后要再去删掉 push 的 name
            parents.pop();
        });
        return result;
    }

    // 通过解析后的数据 循环创建路由
    function _init() {
        // 遵循约定优于配置的原则自动批量注册路由
        angular.forEach(_parseData, function (state, name) {
            var paths = name.split('.'), // base.core.msg => base/core/msg
                lastState = name.match(/(\w+)$/)[0]; // base.core.msg => msg
            if (state.urlParams) {
                lastState = state.name + '/' + state.urlParams;
            }
            angular.extend(state, {
                url: '/' + lastState,
                resolve: _resolveFor(name)
            });
            if (state.controller !== false) {
                state.controller = state.controller || name;
            }
            if (state.templateUrl !== false) {
                paths.push(paths[paths.length - 1]);
                state.templateUrl = _viewPrefix + paths.join('/') + '.html';
            }
            state.controllerAs = state.controllerAs || ctrlName(paths);
            // 循环创建 state
            $stateProvider.state(name, state);
            if (state.abstract && state.items && state.items.length) {
                $urlRouterProvider.when(state.url, [function () {
                    var firstChild = state.items[0];
                    var names = firstChild.name.split('.');
                    return state.url + '/' + names.pop();
                }]);
            }
        });
    }

    function ctrlName(paths) {
        if (paths.length === 0) {
            return '';
        }
        var prefix = '$';
        var name = prefix + paths.shift();
        paths.reverse().shift();
        angular.forEach(paths, function (item) {
            name += item.replace(/\w/, function (v) {
                return v.toUpperCase();
            })
        });
        return name;
    }

    // Generates a resolve object by passing script names
    function _resolveFor(name) {
        return {
            deps: ['$ocLazyLoad', '$q', function ($ocLL, $q) {
                // Creates a promise chain for each argument
                var promise = $q.when(1); // empty promise
                return promise.then(function () {
                    // if is a module, pass the name. If not,
                    // pass the array
                    var whatToLoad = _getRequired(name);
                    // 没找到匹配的文件
                    if (!whatToLoad) {
                        return;
                    }
                    // 返回 promise
                    return $ocLL.load(whatToLoad);
                });
            }]
        };
    }

    // 查找配置中相应的js文件
    function _getRequired(name) {
        var state = _parseData[name], fileObj = state['files'] || [], files = [], hasHttpPrefix = /^http(s?):\/\//;
        if (state.controller !== false) {
            if (!name) {
                return console.error('请设置 route 的 name 属性');
            }
            var paths = name.split('.');
            //// 把controller文件放到name目录里面 而不是与 name 目录同级
            paths.push(paths[paths.length - 1]);
            var ctrlFile = (_jsPathPrefix || '') + paths.join('/') + '.ctrl.js';// TODO 后缀改成配置式的
            files.push(ctrlFile);
        }
        if (state.service !== false) {
            if (!name) {
                return console.error('请设置 route 的 name 属性');
            }
            var paths = name.split('.');
            //// 把service文件放到name目录里面 而不是与 name 目录同级
            paths.push(paths[paths.length - 1]);
            var svcFile = (_jsPathPrefix || '') + paths.join('/') + '.svc.js';// TODO 后缀改成配置式的
            files.push(svcFile);
        }
        if (!angular.isArray(fileObj)) {
            fileObj = Object.keys(fileObj);
        }
        // files.push(fileObj[0],fileObj[1], fileObj[2], ..);
        Array.prototype.push.apply(files, fileObj);
        return files.map(function (item) {
            return hasHttpPrefix.test(item) ? item : (_filePrefix + item); // 以 http:// 或 https:// 开头的不添加前缀
        });
    }
}
